package com.yituo.mjworld.mvc.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yituo.mjworld.core.exception.MyException;
import com.yituo.mjworld.core.utils.OtherTool;
import com.yituo.mjworld.core.web.core.BaseForm;
import com.yituo.mjworld.core.web.core.Result;
import com.yituo.mjworld.mvc.dao.OrderDao;
import com.yituo.mjworld.mvc.dao.ShopCatDao;
import com.yituo.mjworld.mvc.entity.web.*;
import com.yituo.mjworld.mvc.form.DeleteForm;
import com.yituo.mjworld.mvc.form.QueryForm;
import com.yituo.mjworld.mvc.form.support.order.QueryOrder;
import com.yituo.mjworld.mvc.service.BaseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 订单服务模块
 */
@Service
public class OrderServiceImpl extends BaseService {


  @Autowired
  OrderDao orderDao;
  @Autowired
  ShopCatDao shopCatDao;
  @Autowired
  WxServiceImpl wxService;
  @Autowired
  AccountServerImpl accountServer;


  public TransactionLog getPayLog(String id) {
    return (TransactionLog) this.baseDao.get(TransactionLog.class, id);
  }


  /**
   * 更新预付款记录
   *
   * @return
   */
  public Result updatePrepayLog(Map<String, String> params) {
    Result result = new Result();
    String trandNo = params.get("out_trade_no");
    TransactionLog paylog = (TransactionLog) this.baseDao.get(TransactionLog.class, trandNo);
    if (paylog == null) {
      return result.setResult(false).setMsg("订单不存在");
    }
    if (paylog.getStatus() != WebOrder.STATUS_PAY_END) {
      // 已经支付成功!
      paylog.setPayWay(TransactionLog.WAY_WX_PAY);
      paylog.setStatus(WebOrder.STATUS_WAIT_PAY);
      paylog.setUpdateDate(new Date());
      // 更新预付款记录状态已支付
      this.baseDao.update(paylog);
      // 更新相关的订单记录的状态未已付款
      this.orderDao.updateOrderStatus(paylog.getTransactionId(), WebOrder.STATUS_PAY_END);

      // 开始分配赏金和提成
      accountServer.giftMoney(paylog);
    }
    result.setResult(true).setMsg("支付成功");
    return result;
  }

  /**
   * 是否属于web用户
   *
   * @param userId
   * @param transportId
   * @return
   */
  public boolean isOwnerWebUser(String userId, String transportId) {
    List<WebOrder> list = orderDao.getOrdersByUserIdAndTransportId(userId, transportId);
    if (list != null && list.size() > 0) {
      return true;
    }
    return false;
  }


  /**
   * 获取订单,一般为超级管理员调用
   * 000000000000000 0
   *
   * @param form
   * @return
   */
  @Override
  public JSONObject getList(QueryForm form) {
    QueryOrder queryOrder = (QueryOrder) form;

    String sql = "select " +
        " a.orderId ," +
        " a.productId ," +
        " a.productName ," +
        " a.buyNum ," +
        " a.totalPrice ," +
        " a.finalPrice ," +
        " a.template ," +
        " a.createDate ," +
        " a.updateDate ," +
        " a.userId ," +
        " a.addressId ," +
        " a.userNote ," +
        " a.transportId ," +
        " a.transportStatus ," +
        " a.transactionId ," +
        " a.orderStatus " +
        " from web_order a ";
    String countSql = "select count(a.orderId) from web_order a ";
    String where = "";
    form.getParam().clear();
    if (queryOrder.queryType == QueryOrder.QUERY_TYPE_BY_ORDERID) {
      where = " where a.orderId=:orderId ";
      form.getParam().put("orderId", queryOrder.getOrderId());
    }
    if (queryOrder.queryType == QueryOrder.QUERY_TYPE_BY_USERID) {
      where = " where a.userId=:userId ";
      form.getParam().put("userId", queryOrder.getUserId());
    }
    if (queryOrder.queryType == QueryOrder.QUERY_TYPE_BY_STATUS) {
      where = " where a.orderStatus=:orderStatus";
      form.getParam().put("orderStatus", queryOrder.getStatus());
    }
    sql = sql + where;
    countSql = countSql + where;
    return get(sql, countSql, queryOrder, queryOrder.getParam());
  }

  /**
   * 获取用户的交易记录和订单情况
   *
   * @param form
   * @return
   */
  public JSONObject getListForUser(QueryForm form, String userId) {
    JSONObject result = new JSONObject();
    JSONArray items = new JSONArray();
    long count = 0;
    result.put("rows", items);
    QueryOrder queryOrder = (QueryOrder) form;
    // 查询用户的交易记录条数.
    String countSql = "select count(transactionId) from transaction_log where userId=:userId ";
    String where = "";
    queryOrder.getParam().clear();
    queryOrder.getParam().put("userId", userId);
    /**
     * 查询类型为按订单状态查询时
     */
    if (queryOrder.queryType == QueryOrder.QUERY_TYPE_BY_STATUS && queryOrder.status != 0) {
      where = " and status=:status";
      queryOrder.getParam().put("status", queryOrder.getStatus());
    }

    countSql = countSql + where;
    count = this.baseDao.countBySql(countSql, queryOrder.getParam());
    result.put("total", count);
    if (count == 0) {
      return result;
    }
    // 查询用户的交易记录.
    String hql = "from TransactionLog where userId=:userId ";
    hql = hql + where;
    List<TransactionLog> list = this.baseDao.findByPageUseHql(hql, queryOrder.page, queryOrder.rows, queryOrder.getParam());

    JSONObject item = null;
    String hql2 = null;
    if (list != null && list.size() > 0) {
      for (TransactionLog log : list) {
        item = new JSONObject();
        hql2 = "select " +
            "a.orderId," +
            "a.productId," +
            "a.productName," +
            "a.buyNum," +
            "a.totalPrice," +
            "a.finalPrice," +
            "a.template," +
            "a.createDate," +
            "a.updateDate," +
            "a.userNote," +
            "a.userId," +
            "a.addressId," +
            "a.transportId," +
            "a.orderStatus," +
            "a.transportStatus," +
            "a.transactionId," +
            "b.thumbImgUrl from web_order a left join product b on a.productId=b.id  where a.transactionId=:transactionId";
        Map<String, String> params = new HashMap<String, String>();
        params.put("transactionId", log.getTransactionId());
        List<Map<String,Object>> orders = this.baseDao.findBySql(hql2, params);
        item.put("transactionLog", log);
        item.put("list", orders);
        items.add(item);
      }
    }
    result.put("rows", items);
    return result;
  }


  @Override
  public Result delete(DeleteForm form) {
    Result result = new Result();
    WebOrder order = (WebOrder) baseDao.get(WebOrder.class, form.getId());
    if (order == null) {
      result.result = false;
      result.msg = "欲删除的ID不存在!";
    } else {
      baseDao.delete(order);
      result.result = true;
    }
    return result;
  }

  /**
   * 用户删除订单
   *
   * @return
   */
  public JSONObject deleteByUser(String userId, String orderId) {
    JSONObject result = new JSONObject();
    WebOrder order = orderDao.getOrderByUserIdAndOrderId(userId, orderId);
    if (order == null) {
      result.put("result", false);
      result.put("cause", "欲删除的ID不存在!");
    } else {
      baseDao.delete(order);
      result.put("result", true);
    }
    return result;
  }

  /**
   * 保存或者更新
   *
   * @param baseForm
   * @return
   */
  @Override
  public Result saveOrUpdate(BaseForm baseForm) {
    return null;
  }

  /**
   * 校验前端传来的购物车的数据是否符合规范.
   *
   * @param product       被购买的产品
   * @param wp_template   前端传来的模版
   * @param wp_num        前端传来的购买的数量
   * @param wp_totalPrice 前端传来的购买总价
   * @param wp_finalPrice 前端传来的产品单价
   * @return
   */
  public Result validatePrice(Product product, String wp_template, int wp_num, BigDecimal wp_finalPrice, BigDecimal wp_totalPrice) {
    Result result = new Result();
    String templateStr = this.shopCatDao.getTemplate(product.getId());
    if (StringUtils.isEmpty(templateStr)) {
      if (StringUtils.isEmpty(wp_template)) {
        if (product.getSalePrice().multiply(BigDecimal.valueOf(wp_num)).compareTo(wp_totalPrice) == 0) {
          return result.setResult(true);
        }
        return result.setResult(false).setMsg("总价计算错误!");
      }
      return result.setResult(false).setMsg("数据库模版不存在,非法操作!");
    } else {
      if (StringUtils.isEmpty(wp_template)) {
        return result.setResult(false).setMsg("模版为必填项!");
      }
    }
    BigDecimal finalPrice = product.getSalePrice();
    try {
      JSONArray template_db = JSONArray.parseArray(templateStr);
      JSONArray template_web = JSONArray.parseArray(wp_template);
      if (template_db.size() != template_web.size()) {
        return result.setResult(false).setMsg("两个模版长度不相等");
      }
      for (int i = 0; i < template_web.size(); i++) {
        JSONObject item_db = template_db.getJSONObject(i);
        JSONObject item_web = template_web.getJSONObject(i);
        if (!item_db.getString("n").equals(item_web.getString("n"))) {
          return result.setResult(false).setMsg("模版类型不匹配!");
        }
        JSONArray props_db = item_db.getJSONArray("p");
        JSONArray props_web = item_web.getJSONArray("p");
        if (props_web.size() != 1) {
          return result.setResult(false).setMsg("未选中浮动价格");
        }
        JSONObject p_web = props_web.getJSONObject(0);
        boolean findResult = false;
        for (int j = 0; j < props_db.size(); j++) {
          JSONObject p_db = props_db.getJSONObject(j);
          if (p_db.getString("f").equals(p_web.getString("f"))
              && p_db.getString("n").equals(p_web.getString("n"))) {
            findResult = true;
            break;
          }
        }
        if (findResult == false) {
          return result.setResult(false).setMsg("模版无法匹配!");
        }
        BigDecimal floatPrice = p_web.getBigDecimal("f");
        finalPrice = finalPrice.add(floatPrice);
      }
      BigDecimal totalPrice = finalPrice.multiply(BigDecimal.valueOf(wp_num));
      if (finalPrice.compareTo(wp_finalPrice) == 0) {
        if (totalPrice.compareTo(wp_totalPrice) == 0) {
          return result.setResult(true);
        }
        return result.setResult(false).setMsg("总价计算错误!");
      }
      return result.setResult(false).setMsg("商品的最终销售价错误!");
    } catch (Exception e) {
      return result.setResult(false).setMsg("模版校验失败!");
    }
  }

  /**
   * 产品全都存在,且价格合理,返回真.不存在,返回假
   *
   * @return
   */
  public Result validateParams(String recordArray, BigDecimal totalPrice, String userId) {
    Result result = new Result();
    if (StringUtils.isEmpty(recordArray)) {
      return result.setResult(false).setMsg("空数组!");
    }
    String[] arr = recordArray.replace("[", "").replace("]", "").split(",");
    for (String a : arr) {
      if (Integer.parseInt(a) <= 0) {
        return result.setResult(false).setMsg("数组中的内容某项小于等于0!");
      }
    }
    String where = recordArray.replace("[", "(").replace("]", ")");
    String sql = "select count(id) from web_shop_cut where userId=:userId and id in " + where;
    BigInteger i = (BigInteger) this.baseDao.getSession().createNativeQuery(sql).setParameter("userId", userId).uniqueResult();
    if (i.compareTo(BigInteger.valueOf(arr.length)) != 0) {
      return result.setResult(false).setMsg("数据库中查询到的记录数量和数组长度不相等!");
    }
    sql = "select sum(finalPrice*num) from web_shop_cut where userId=:userId and id in " + where;
    BigDecimal totalPriceDB = (BigDecimal) this.baseDao.getSession().createNativeQuery(sql).setParameter("userId", userId).uniqueResult();
    System.out.println(totalPriceDB);
    System.out.println(totalPrice);
    System.out.println(totalPriceDB.compareTo(totalPrice));
    if (totalPriceDB.compareTo(totalPrice) != 0) {
      return result.setResult(false).setMsg("数据库中查询到的记录总价和前端价格不相等!");
    }
    return result.setResult(true);
  }

  /**
   * 批量创建订单
   *
   * @param recordsStr 购物车中被选中结算的记录的ID数组
   * @param totalPrice 购物车中被选中结算的记录的总价
   * @param addressId  用户的收货地址
   * @param userNote   用户的买家留言
   * @param user       购买产品的用户
   * @return 购买成功返回真以及交易记录ID, 购买失败返回假或者抛出异常.
   * @throws MyException
   */
  public Result createOrders(String recordsStr, BigDecimal totalPrice, int addressId, String userNote, WebUser user) throws MyException {
    String[] recordArr = recordsStr.replace("[", "").replace("]", "").split(",");

    Result result = new Result();
    // 1.创建一条默认的支付记录.
    TransactionLog paylog = new TransactionLog();
    paylog.setTransactionId(OtherTool.getUUID());
    paylog.setAmount(totalPrice);
    paylog.setCreateDate(new Date());
    paylog.setPayWay(TransactionLog.WAY_WX_PAY);
    paylog.setStatus(WebOrder.STATUS_WAIT_PAY);
    paylog.setCreateDate(new Date());
    paylog.setUpdateDate(new Date());
    paylog.setUserId(user.getId());
    paylog.setUserNote(userNote);
    this.baseDao.save(paylog);

    for (String recordId : recordArr) {
      // 1.获取购物车中的记录
      WebShopCut webShopCut = (WebShopCut) this.baseDao.get(WebShopCut.class, Integer.parseInt(recordId));
      // 2.获取对应产品的信息
      Product product = (Product) this.baseDao.get(Product.class, webShopCut.getProductId());
      // 3.创建订单
      WebOrder webOrder = new WebOrder();
      webOrder.setOrderId(OtherTool.getUUID());
      webOrder.setUserId(user.getId());
      webOrder.setCreateDate(new Date());
      webOrder.setProductName(product.getName());
      webOrder.setProductId(product.getId());
      webOrder.setAddressId(addressId);
      webOrder.setBuyNum(webShopCut.getNum());
      webOrder.setFinalPrice(webShopCut.getFinalPrice());
      webOrder.setTotalPrice(webShopCut.getTotalPrice());
      webOrder.setTemplate(webShopCut.getTemplate());
      webOrder.setTransactionId(paylog.getTransactionId());
      webOrder.setOrderStatus(WebOrder.STATUS_WAIT_PAY);
      webOrder.setUserNote(userNote);
      // 4.保存订单
      Serializable id = this.baseDao.save(webOrder);
      if (id != null && !StringUtils.isEmpty(id)) {
        continue;
      } else {
        // 5.触发回滚!
        throw new MyException("创建订单失败");
      }
    }
    return result.setResult(true).setMsg(paylog.getTransactionId());
  }

  /**
   * 创建订单.
   * <p>
   * 此接口调用场景,立即购买,此时提交的表单 正好是一个order表的一个子属性集合.
   *
   * @param order   用户提交的订单表
   * @param product 用户购买的产品实体
   * @param user    购买产品的用户
   * @return
   * @throws MyException
   */
  public Result createOrder(WebOrder order, Product product, WebUser user, String openId, String ip) throws MyException {
    Result result = new Result();
    // 1.创建一条预付款_支付记录.
    TransactionLog paylog = new TransactionLog();
    paylog.setTransactionId(OtherTool.getUUID());
    paylog.setAmount(order.getTotalPrice());
    paylog.setCreateDate(new Date());
    paylog.setPayWay(TransactionLog.WAY_WX_PAY);
    paylog.setStatus(WebOrder.STATUS_WAIT_PAY);
    paylog.setCreateDate(new Date());
    paylog.setUpdateDate(new Date());
    paylog.setUserId(user.getId());
    this.baseDao.save(paylog);

    // 2.创建订单
    order.setOrderId(OtherTool.getUUID());
    order.setUserId(user.getId());
    order.setCreateDate(new Date());
    order.setProductName(product.getName());
    order.setTransactionId(paylog.getTransactionId());
    Serializable id = this.baseDao.save(order);
    if (StringUtils.isEmpty(id)) {
      // 触发回滚!
      throw new MyException("创建订单失败");
    }
    // 3.请求微信生成预付款订单
    Map<String, String> requestResult = null;
    try {
      int total_fee = paylog.getAmount().multiply(BigDecimal.valueOf(100)).intValue();
      requestResult = wxService.unifiedorder(openId, paylog.getTransactionId(), ip, total_fee);
      if (requestResult != null && requestResult.get("return_code").equals("SUCCESS")) {
        Map<String, String> map = wxService.getWxPayConfig(requestResult);
        if (map == null) {
          return result.setResult(false).setMsg("微信支付配置签名失败!");
        }
        return result.setResult(true).setMsg(map);
      } else {
        // 触发回滚
        throw new MyException("请求微信的预付款订单失败!");
      }
    } catch (IOException e) {
      e.printStackTrace();
      // 触发回滚!
      throw new MyException("创建订单失败");
    }
  }
}
